package cm.tl.pms.sys.mvc;

import cm.tl.pms.sys.satoken.EasySaInterceprot;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @author laker
 */
@Configuration
@Slf4j
public class WebMvcConfig implements WebMvcConfigurer {
    private static final String[] exclude_path = {"/admin/**",
            "/admin/login.html",
            "/error",
            "/swagger-resources/**",
            "/sys/auth/v1/login",
            "/spider/*",
            // 手机号登录
            "/sys/auth/v1/loginPhone",
            // 发送验证码
            "/sys/auth/sendCode",
            // 验证验证码
            "/sys/auth/verifyCode",
            // 手机号重置密码
            "/sys/auth/passwordResetPhone",
            // 邮箱重置密码
            "/sys/auth/passwordResetEmail",
            // 手机号注册
            "/sys/user/signInPhone",
            // 邮箱注册
            "/sys/user/signInEmail",
            // 发送邮箱验证码-密码找回
            "/email/sendEmailCode",
            // 发送邮箱验证码-注册
            "/email/sendEmailCodeSignIn",
            // 手机号发送验证码-密码找回
            "/phone/sendCode",
            // 手机号发送验证码-账号注册
            "/phone/sendCodeSignIn",
            // hertzbeat 配置
            "/heapdump",
            "/actuator/**",
            "/metrics/**",
            "/aiDataResource/insertFileType",
            "/trace"

    };
    private static final String[] trace_exclude_path = {"/admin/**",
            "/admin/login.html",
            "/error",
            "/swagger-resources/**"};


    /**
     * 注册sa-token的拦截器，打开注解式鉴权功能
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册注解拦截器，并排除不需要注解鉴权的接口地址
        registry.addInterceptor(new EasySaInterceprot(handler ->
                                SaRouter.match("/**", r -> StpUtil.checkLogin()))
//                        .isAnnotation(true)       //@SaCheckPermission注解校验关闭
                )
                .addPathPatterns("/**")
                .excludePathPatterns(exclude_path);

    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // 路由匹配规则
    }

    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
        // 配置异常解析器
    }


    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        // 添加自定义方法参数处理器
        // 添加请求参数的PageRequest对象自动填充
        argumentResolvers.add(new PageRequestArgumentResolver());
        // 添加请求参数 CurrentUser对象自动填充
        argumentResolvers.add(new HandlerMethodArgumentResolver() {
            @Override
            public boolean supportsParameter(MethodParameter parameter) {
                return CurrentUser.class.equals(parameter.getParameterType());
            }

            @Override
            public Object resolveArgument(
                    MethodParameter parameter,
                    ModelAndViewContainer mvContainer,
                    NativeWebRequest nativeWebRequest,
                    WebDataBinderFactory webDataBinderFactory) throws Exception {
                HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
                if (request == null) {
                    return null;
                }
                // CurrentUser  = from request
                return CurrentUser.builder().id(StpUtil.getLoginId().toString()).build();
            }
        });
    }
}
